{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"http://hilpisch.com/tpq_logo.png\" alt=\"The Python Quants\" width=\"35%\" align=\"right\" border=\"0\"><br>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python for Finance (2nd ed.)\n",
    "\n",
    "**Mastering Data-Driven Finance**\n",
    "\n",
    "&copy; Dr. Yves J. Hilpisch | The Python Quants GmbH\n",
    "\n",
    "<img src=\"http://hilpisch.com/images/py4fi_2nd_shadow.png\" width=\"300px\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Performance Python"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Loops"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def average_py(n):\n",
    "    s = 0  \n",
    "    for i in range(n):\n",
    "        s += random.random()  \n",
    "    return s / n  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 10000000  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.1 s, sys: 6.25 ms, total: 1.1 s\n",
      "Wall time: 1.1 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.4999986823484931"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time average_py(n)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "992 ms ± 17 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit average_py(n)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.22 s, sys: 158 ms, total: 1.38 s\n",
      "Wall time: 1.38 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.5000525540381814"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time sum([random.random() for _ in range(n)]) / n  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def average_np(n):\n",
    "    s = np.random.random(n)  \n",
    "    return s.mean()  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 143 ms, sys: 34.8 ms, total: 178 ms\n",
      "Wall time: 178 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.5001596021926673"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time average_np(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "115 ms ± 2.54 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit average_np(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "80000000"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = np.random.random(n)\n",
    "s.nbytes  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numba"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numba"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "average_nb = numba.jit(average_py)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 187 ms, sys: 23 ms, total: 210 ms\n",
      "Wall time: 230 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.4999844106661735"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time average_nb(n)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 66.2 ms, sys: 511 µs, total: 66.7 ms\n",
      "Wall time: 66.3 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.4998076442664921"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time average_nb(n)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64.9 ms ± 1.37 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit average_nb(n)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cython"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext Cython"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_3441afa2b270e532997ee8428fb82a3d.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython  { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-8\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">1</span>: <span class=\"k\">import</span> <span class=\"nn\">random</span></pre>\n",
       "<pre class='cython code score-8 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_Import</span>(__pyx_n_s_random, 0, 0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_random, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 1, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-26\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">2</span>: <span class=\"k\">def</span> <span class=\"nf\">average_cy1</span><span class=\"p\">(</span><span class=\"nb\">int</span> <span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-26 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_3441afa2b270e532997ee8428fb82a3d_1average_cy1(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_3441afa2b270e532997ee8428fb82a3d_1average_cy1 = {\"average_cy1\", (PyCFunction)__pyx_pw_46_cython_magic_3441afa2b270e532997ee8428fb82a3d_1average_cy1, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_3441afa2b270e532997ee8428fb82a3d_1average_cy1(PyObject *__pyx_self, PyObject *__pyx_arg_n) {\n",
       "  int __pyx_v_n;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"average_cy1 (wrapper)\", 0);\n",
       "  assert(__pyx_arg_n); {\n",
       "    __pyx_v_n = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(__pyx_arg_n); if (unlikely((__pyx_v_n == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L3_error)</span>\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_3441afa2b270e532997ee8428fb82a3d.average_cy1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_3441afa2b270e532997ee8428fb82a3d_average_cy1(__pyx_self, ((int)__pyx_v_n));\n",
       "\n",
       "  /* function exit code */\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_3441afa2b270e532997ee8428fb82a3d_average_cy1(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_n) {\n",
       "  CYTHON_UNUSED int __pyx_v_i;\n",
       "  float __pyx_v_s;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"average_cy1\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_6);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_7);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_3441afa2b270e532997ee8428fb82a3d.average_cy1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple_ = <span class='py_c_api'>PyTuple_Pack</span>(4, __pyx_n_s_n, __pyx_n_s_n, __pyx_n_s_i, __pyx_n_s_s);<span class='error_goto'> if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple_);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple_);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_3441afa2b270e532997ee8428fb82a3d_1average_cy1, NULL, __pyx_n_s_cython_magic_3441afa2b270e53299);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_average_cy1, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">3</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">4</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">s</span> <span class=\"o\">=</span> <span class=\"mf\">0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_s = 0.0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">5</span>:     <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_1 = __pyx_v_n;\n",
       "  __pyx_t_2 = __pyx_t_1;\n",
       "  for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n",
       "    __pyx_v_i = __pyx_t_3;\n",
       "</pre><pre class=\"cython line score-44\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">6</span>:         <span class=\"n\">s</span> <span class=\"o\">+=</span> <span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">random</span><span class=\"p\">()</span></pre>\n",
       "<pre class='cython code score-44 '>    __pyx_t_4 = <span class='py_c_api'>PyFloat_FromDouble</span>(__pyx_v_s);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "    <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_6, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "    __pyx_t_7 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_6, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_7);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    __pyx_t_6 = NULL;\n",
       "    if (CYTHON_UNPACK_METHODS &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_7))) {\n",
       "      __pyx_t_6 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_7);\n",
       "      if (likely(__pyx_t_6)) {\n",
       "        PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_7);\n",
       "        <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_6);\n",
       "        <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
       "        <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_7, function);\n",
       "      }\n",
       "    }\n",
       "    __pyx_t_5 = (__pyx_t_6) ? <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_7, __pyx_t_6) : <span class='pyx_c_api'>__Pyx_PyObject_CallNoArg</span>(__pyx_t_7);\n",
       "    <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    if (unlikely(!__pyx_t_5)) <span class='error_goto'>__PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_7); __pyx_t_7 = 0;\n",
       "    __pyx_t_7 = <span class='py_c_api'>PyNumber_InPlaceAdd</span>(__pyx_t_4, __pyx_t_5);<span class='error_goto'> if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_7);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    __pyx_t_8 = __pyx_<span class='py_c_api'>PyFloat_AsFloat</span>(__pyx_t_7); if (unlikely((__pyx_t_8 == (float)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_7); __pyx_t_7 = 0;\n",
       "    __pyx_v_s = __pyx_t_8;\n",
       "  }\n",
       "</pre><pre class=\"cython line score-11\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">7</span>:     <span class=\"k\">return</span> <span class=\"n\">s</span> <span class=\"o\">/</span> <span class=\"n\">n</span></pre>\n",
       "<pre class='cython code score-11 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  if (unlikely(__pyx_v_n == 0)) {\n",
       "    <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "    <span class='error_goto'>__PYX_ERR(0, 7, __pyx_L1_error)</span>\n",
       "  }\n",
       "  __pyx_t_7 = <span class='py_c_api'>PyFloat_FromDouble</span>((__pyx_v_s / ((float)__pyx_v_n)));<span class='error_goto'> if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 7, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_7);\n",
       "  __pyx_r = __pyx_t_7;\n",
       "  __pyx_t_7 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "import random  \n",
    "def average_cy1(int n):  \n",
    "    cdef int i  \n",
    "    cdef float s = 0  \n",
    "    for i in range(n):\n",
    "        s += random.random()\n",
    "    return s / n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 573 ms, sys: 1.86 ms, total: 575 ms\n",
      "Wall time: 573 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.5000302195549011"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time average_cy1(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "570 ms ± 7.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit average_cy1(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.6792964339256287\n",
      "0.934692919254303\n",
      "0.3835020661354065\n",
      "0.5194163918495178\n",
      "0.8309653401374817\n"
     ]
    }
   ],
   "source": [
    "%%cython\n",
    "from libc.stdlib cimport rand  \n",
    "cdef extern from 'limits.h':  \n",
    "    int INT_MAX  \n",
    "cdef int i\n",
    "cdef float rn\n",
    "for i in range(5):\n",
    "    rn = rand() / INT_MAX  \n",
    "    print(rn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython  { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-0\">&#xA0;<span class=\"\">1</span>: <span class=\"k\">from</span> <span class=\"nn\">libc.stdlib</span> <span class=\"k\">cimport</span> <span class=\"n\">rand</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">2</span>: <span class=\"k\">cdef</span> <span class=\"kr\">extern</span> <span class=\"k\">from</span> <span class=\"s\">&#39;limits.h&#39;</span><span class=\"p\">:</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">3</span>:     <span class=\"nb\">int</span> <span class=\"n\">INT_MAX</span></pre>\n",
       "<pre class=\"cython line score-23\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">4</span>: <span class=\"k\">def</span> <span class=\"nf\">average_cy2</span><span class=\"p\">(</span><span class=\"nb\">int</span> <span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-23 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7_1average_cy2(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7_1average_cy2 = {\"average_cy2\", (PyCFunction)__pyx_pw_46_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7_1average_cy2, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7_1average_cy2(PyObject *__pyx_self, PyObject *__pyx_arg_n) {\n",
       "  int __pyx_v_n;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"average_cy2 (wrapper)\", 0);\n",
       "  assert(__pyx_arg_n); {\n",
       "    __pyx_v_n = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(__pyx_arg_n); if (unlikely((__pyx_v_n == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L3_error)</span>\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7.average_cy2\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7_average_cy2(__pyx_self, ((int)__pyx_v_n));\n",
       "\n",
       "  /* function exit code */\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7_average_cy2(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_n) {\n",
       "  CYTHON_UNUSED int __pyx_v_i;\n",
       "  float __pyx_v_s;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"average_cy2\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7.average_cy2\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple_ = <span class='py_c_api'>PyTuple_Pack</span>(4, __pyx_n_s_n, __pyx_n_s_n, __pyx_n_s_i, __pyx_n_s_s);<span class='error_goto'> if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 4, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple_);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple_);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_9c63ce5f435876be5d32cdf4e9fd91e7_1average_cy2, NULL, __pyx_n_s_cython_magic_9c63ce5f435876be5d);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_average_cy2, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">5</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">6</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">s</span> <span class=\"o\">=</span> <span class=\"mf\">0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_s = 0.0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">7</span>:     <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_1 = __pyx_v_n;\n",
       "  __pyx_t_2 = __pyx_t_1;\n",
       "  for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n",
       "    __pyx_v_i = __pyx_t_3;\n",
       "</pre><pre class=\"cython line score-5\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">8</span>:         <span class=\"n\">s</span> <span class=\"o\">+=</span> <span class=\"n\">rand</span><span class=\"p\">()</span> <span class=\"o\">/</span> <span class=\"n\">INT_MAX</span></pre>\n",
       "<pre class='cython code score-5 '>    __pyx_t_4 = rand();\n",
       "    if (unlikely(INT_MAX == 0)) {\n",
       "      <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "      <span class='error_goto'>__PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "    }\n",
       "    __pyx_v_s = (__pyx_v_s + (((double)__pyx_t_4) / ((double)INT_MAX)));\n",
       "  }\n",
       "</pre><pre class=\"cython line score-11\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">9</span>:     <span class=\"k\">return</span> <span class=\"n\">s</span> <span class=\"o\">/</span> <span class=\"n\">n</span></pre>\n",
       "<pre class='cython code score-11 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  if (unlikely(__pyx_v_n == 0)) {\n",
       "    <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "    <span class='error_goto'>__PYX_ERR(0, 9, __pyx_L1_error)</span>\n",
       "  }\n",
       "  __pyx_t_5 = <span class='py_c_api'>PyFloat_FromDouble</span>((__pyx_v_s / ((float)__pyx_v_n)));<span class='error_goto'> if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "  __pyx_r = __pyx_t_5;\n",
       "  __pyx_t_5 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "from libc.stdlib cimport rand  \n",
    "cdef extern from 'limits.h':  \n",
    "    int INT_MAX  \n",
    "def average_cy2(int n):\n",
    "    cdef int i\n",
    "    cdef float s = 0\n",
    "    for i in range(n):\n",
    "        s += rand() / INT_MAX  \n",
    "    return s / n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 62 ms, sys: 315 µs, total: 62.4 ms\n",
      "Wall time: 62.2 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.500017523765564"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time average_cy2(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "59.3 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit average_cy2(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Prime Numbers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pure Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_prime(I):\n",
    "    if I % 2 == 0: return False  \n",
    "    for i in range(3, int(I ** 0.5) + 1, 2):  \n",
    "        if I % i == 0: return False  \n",
    "    return True  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100000003"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n = int(1e8 + 3)  \n",
    "n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 27 µs, sys: 1 µs, total: 28 µs\n",
      "Wall time: 29.8 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100000007"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p1 = int(1e8 + 7)  \n",
    "p1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 345 µs, sys: 0 ns, total: 345 µs\n",
      "Wall time: 349 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime(p1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "p2 = 100109100129162907  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "57"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p2.bit_length()  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 16.7 s, sys: 21.8 ms, total: 16.7 s\n",
      "Wall time: 16.8 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime(p2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numba"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "is_prime_nb = numba.jit(is_prime)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 71.9 ms, sys: 5.55 ms, total: 77.4 ms\n",
      "Wall time: 78.2 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime_nb(n)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 7 µs, sys: 1 µs, total: 8 µs\n",
      "Wall time: 11 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime_nb(n)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 28 µs, sys: 0 ns, total: 28 µs\n",
      "Wall time: 31.9 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime_nb(p1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.5 s, sys: 7.02 ms, total: 1.5 s\n",
      "Wall time: 1.5 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime_nb(p2)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cython"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%cython\n",
    "def is_prime_cy1(I):\n",
    "    if I % 2 == 0: return False\n",
    "    for i in range(3, int(I ** 0.5) + 1, 2):\n",
    "        if I % i == 0: return False\n",
    "    return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "345 µs ± 2.91 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit is_prime(p1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "207 µs ± 2.86 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit is_prime_cy1(p1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%cython\n",
    "def is_prime_cy2(long I):  \n",
    "    cdef long i  \n",
    "    if I % 2 == 0: return False\n",
    "    for i in range(3, int(I ** 0.5) + 1, 2):\n",
    "        if I % i == 0: return False\n",
    "    return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "44.6 µs ± 1.72 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit is_prime_cy2(p1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.55 s, sys: 11.3 ms, total: 1.57 s\n",
      "Wall time: 1.56 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime_nb(p2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.42 s, sys: 8.89 ms, total: 1.43 s\n",
      "Wall time: 1.42 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time is_prime_cy2(p2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multiprocessing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "import multiprocessing as mp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "pool = mp.Pool(processes=4)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.3 ms, sys: 1.74 ms, total: 3.04 ms\n",
      "Wall time: 4.09 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[True, True, True, True, True, True, True, True, True, True]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time pool.map(is_prime, 10 * [p1])  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 9.26 ms, sys: 6.19 ms, total: 15.5 ms\n",
      "Wall time: 5.53 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[True, True, True, True, True, True, True, True, True, True]"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time pool.map(is_prime_nb, 10 * [p2])  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 4.08 ms, sys: 2 ms, total: 6.07 ms\n",
      "Wall time: 4.53 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[True, True, True, True, True, True, True, True, True, True]"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time pool.map(is_prime_cy2, 10 * [p2])  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fibonacci Numbers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Recursive Algorithm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fib_rec_py1(n):\n",
    "    if n < 2:\n",
    "        return n\n",
    "    else:\n",
    "        return fib_rec_py1(n - 1) + fib_rec_py1(n - 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 3.72 s, sys: 10.9 ms, total: 3.73 s\n",
      "Wall time: 3.74 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "9227465"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_rec_py1(35)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "fib_rec_nb = numba.jit(fib_rec_py1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 3.76 s, sys: 33.3 ms, total: 3.79 s\n",
      "Wall time: 3.8 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "9227465"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_rec_nb(35)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%cython\n",
    "def fib_rec_cy(int n):\n",
    "    if n < 2:\n",
    "        return n\n",
    "    else:\n",
    "        return fib_rec_cy(n - 1) + fib_rec_cy(n - 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 671 ms, sys: 5.86 ms, total: 676 ms\n",
      "Wall time: 670 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "9227465"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_rec_cy(35)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import lru_cache as cache"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "@cache(maxsize=None)  \n",
    "def fib_rec_py2(n):\n",
    "    if n < 2:\n",
    "        return n\n",
    "    else:\n",
    "        return fib_rec_py2(n - 1) + fib_rec_py2(n - 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 46 µs, sys: 24 µs, total: 70 µs\n",
      "Wall time: 73 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "9227465"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_rec_py2(35)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 37 µs, sys: 6 µs, total: 43 µs\n",
      "Wall time: 47.2 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "23416728348467685"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_rec_py2(80)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Iterative Algorithm "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fib_it_py(n):\n",
    "    x, y = 0, 1\n",
    "    for i in range(1, n + 1):\n",
    "        x, y = y, x + y\n",
    "    return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 12 µs, sys: 5 µs, total: 17 µs\n",
      "Wall time: 19.8 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "23416728348467685"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_it_py(80)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "fib_it_nb = numba.jit(fib_it_py)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 44 ms, sys: 5.24 ms, total: 49.3 ms\n",
      "Wall time: 48.7 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "23416728348467685"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_it_nb(80)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 5 µs, sys: 1e+03 ns, total: 6 µs\n",
      "Wall time: 7.87 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "23416728348467685"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_it_nb(80)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%cython\n",
    "def fib_it_cy1(int n):\n",
    "    cdef long i\n",
    "    cdef long x = 0, y = 1\n",
    "    for i in range(1, n + 1):\n",
    "        x, y = y, x + y\n",
    "    return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 3 µs, sys: 1e+03 ns, total: 4 µs\n",
      "Wall time: 7.15 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "23416728348467685"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_it_cy1(80)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9969216677189303386214405760200\n",
      "CPU times: user 112 µs, sys: 42 µs, total: 154 µs\n",
      "Wall time: 149 µs\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "fn = fib_rec_py2(150)  \n",
    "print(fn)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "103"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn.bit_length()  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6792540214324356296\n",
      "CPU times: user 39 µs, sys: 7 µs, total: 46 µs\n",
      "Wall time: 45.1 µs\n"
     ]
    }
   ],
   "source": [
    "%%time \n",
    "fn = fib_it_nb(150)  \n",
    "print(fn)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "63"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn.bit_length()  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6792540214324356296\n",
      "CPU times: user 45 µs, sys: 19 µs, total: 64 µs\n",
      "Wall time: 56 µs\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "fn = fib_it_cy1(150)  \n",
    "print(fn)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "63"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn.bit_length()  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%cython\n",
    "cdef extern from *:\n",
    "    ctypedef int int128 '__int128_t'  \n",
    "def fib_it_cy2(int n):\n",
    "    cdef int128 i  \n",
    "    cdef int128 x = 0, y = 1  \n",
    "    for i in range(1, n + 1):\n",
    "        x, y = y, x + y\n",
    "    return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9969216677189303386214405760200\n",
      "CPU times: user 51 µs, sys: 21 µs, total: 72 µs\n",
      "Wall time: 67 µs\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "fn = fib_it_cy2(150)  \n",
    "print(fn)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "103"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn.bit_length()  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Number Pi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The code example is taken from [StackExchange](https://codereview.stackexchange.com/questions/69370/monte-carlo-pi-calculation)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "import numpy as np\n",
    "from pylab import mpl, plt\n",
    "plt.style.use('seaborn')\n",
    "mpl.rcParams['font.family'] = 'serif'\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "rn = [(random.random() * 2 - 1, random.random() * 2 - 1)\n",
    "      for _ in range(500)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.53703897, -0.76309537],\n",
       "       [-0.8172364 ,  0.17231555],\n",
       "       [ 0.35921789,  0.48845774],\n",
       "       [-0.85126377,  0.73021135],\n",
       "       [ 0.92217276, -0.45470297]])"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rn = np.array(rn)\n",
    "rn[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-1.1, 1.1)"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 504x504 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(7, 7))\n",
    "ax = fig.add_subplot(1, 1, 1)\n",
    "circ = plt.Circle((0, 0), radius=1, edgecolor='g', lw=2.0,\n",
    "                  facecolor='None')  \n",
    "box = plt.Rectangle((-1, -1), 2, 2, edgecolor='b', alpha=0.3)  \n",
    "ax.add_patch(circ)  \n",
    "ax.add_patch(box)  \n",
    "plt.plot(rn[:, 0], rn[:, 1], 'r.')  \n",
    "plt.ylim(-1.1, 1.1)\n",
    "plt.xlim(-1.1, 1.1)\n",
    "# plt.savefig('../../images/ch10/perf_01.png');"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = int(1e7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 369 ms, sys: 65.6 ms, total: 435 ms\n",
      "Wall time: 414 ms\n"
     ]
    }
   ],
   "source": [
    "%time rn = np.random.random((n, 2)) * 2 - 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "160000000"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rn.nbytes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 850 ms, sys: 305 ms, total: 1.15 s\n",
      "Wall time: 696 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.946, 0.319, 0.708, 0.739, 1.266, 0.617, 0.995, 0.537])"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time distance = np.sqrt((rn ** 2).sum(axis=1))  \n",
    "distance[:8].round(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 88.6 ms, sys: 5.19 ms, total: 93.8 ms\n",
      "Wall time: 25 ms\n"
     ]
    }
   ],
   "source": [
    "%time frac = (distance <= 1.0).sum() / len(distance)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.141768"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pi_mcs = frac * 4  \n",
    "pi_mcs  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mcs_pi_py(n):\n",
    "    circle = 0\n",
    "    for _ in range(n):\n",
    "        x, y = random.random(), random.random()\n",
    "        if (x ** 2 + y ** 2) ** 0.5 <= 1:\n",
    "            circle += 1\n",
    "    return (4 * circle) / n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 4.88 s, sys: 23.3 ms, total: 4.91 s\n",
      "Wall time: 4.56 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3.142974"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time mcs_pi_py(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [],
   "source": [
    "mcs_pi_nb = numba.jit(mcs_pi_py)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 341 ms, sys: 10.5 ms, total: 351 ms\n",
      "Wall time: 356 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3.1418196"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time mcs_pi_nb(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 162 ms, sys: 1.43 ms, total: 163 ms\n",
      "Wall time: 162 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3.140844"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time mcs_pi_nb(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_5becc8af26d5a48aee95fde3029f1578.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython  { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-8\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">1</span>: <span class=\"k\">import</span> <span class=\"nn\">random</span></pre>\n",
       "<pre class='cython code score-8 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_Import</span>(__pyx_n_s_random, 0, 0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_random, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 1, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-25\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">2</span>: <span class=\"k\">def</span> <span class=\"nf\">mcs_pi_cy1</span><span class=\"p\">(</span><span class=\"nb\">int</span> <span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-25 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_5becc8af26d5a48aee95fde3029f1578_1mcs_pi_cy1(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_5becc8af26d5a48aee95fde3029f1578_1mcs_pi_cy1 = {\"mcs_pi_cy1\", (PyCFunction)__pyx_pw_46_cython_magic_5becc8af26d5a48aee95fde3029f1578_1mcs_pi_cy1, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_5becc8af26d5a48aee95fde3029f1578_1mcs_pi_cy1(PyObject *__pyx_self, PyObject *__pyx_arg_n) {\n",
       "  int __pyx_v_n;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"mcs_pi_cy1 (wrapper)\", 0);\n",
       "  assert(__pyx_arg_n); {\n",
       "    __pyx_v_n = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(__pyx_arg_n); if (unlikely((__pyx_v_n == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L3_error)</span>\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_5becc8af26d5a48aee95fde3029f1578.mcs_pi_cy1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_5becc8af26d5a48aee95fde3029f1578_mcs_pi_cy1(__pyx_self, ((int)__pyx_v_n));\n",
       "\n",
       "  /* function exit code */\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_5becc8af26d5a48aee95fde3029f1578_mcs_pi_cy1(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_n) {\n",
       "  CYTHON_UNUSED int __pyx_v_i;\n",
       "  int __pyx_v_circle;\n",
       "  float __pyx_v_x;\n",
       "  float __pyx_v_y;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"mcs_pi_cy1\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_6);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_5becc8af26d5a48aee95fde3029f1578.mcs_pi_cy1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple_ = <span class='py_c_api'>PyTuple_Pack</span>(6, __pyx_n_s_n, __pyx_n_s_n, __pyx_n_s_i, __pyx_n_s_circle, __pyx_n_s_x, __pyx_n_s_y);<span class='error_goto'> if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple_);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple_);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_5becc8af26d5a48aee95fde3029f1578_1mcs_pi_cy1, NULL, __pyx_n_s_cython_magic_5becc8af26d5a48aee);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_mcs_pi_cy1, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">3</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span><span class=\"p\">,</span> <span class=\"nf\">circle</span> <span class=\"o\">=</span> <span class=\"mf\">0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_circle = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">4</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">x</span><span class=\"p\">,</span> <span class=\"nf\">y</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">5</span>:     <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_1 = __pyx_v_n;\n",
       "  __pyx_t_2 = __pyx_t_1;\n",
       "  for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n",
       "    __pyx_v_i = __pyx_t_3;\n",
       "</pre><pre class=\"cython line score-64\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">6</span>:         <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"o\">=</span> <span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">random</span><span class=\"p\">(),</span> <span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">random</span><span class=\"p\">()</span></pre>\n",
       "<pre class='cython code score-64 '>    <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_5, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "    __pyx_t_6 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_5, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    __pyx_t_5 = NULL;\n",
       "    if (CYTHON_UNPACK_METHODS &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_6))) {\n",
       "      __pyx_t_5 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_6);\n",
       "      if (likely(__pyx_t_5)) {\n",
       "        PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_6);\n",
       "        <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_5);\n",
       "        <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
       "        <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_6, function);\n",
       "      }\n",
       "    }\n",
       "    __pyx_t_4 = (__pyx_t_5) ? <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_6, __pyx_t_5) : <span class='pyx_c_api'>__Pyx_PyObject_CallNoArg</span>(__pyx_t_6);\n",
       "    <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    if (unlikely(!__pyx_t_4)) <span class='error_goto'>__PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    __pyx_t_7 = __pyx_<span class='py_c_api'>PyFloat_AsFloat</span>(__pyx_t_4); if (unlikely((__pyx_t_7 == (float)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_6, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "    __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_6, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    __pyx_t_6 = NULL;\n",
       "    if (CYTHON_UNPACK_METHODS &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_5))) {\n",
       "      __pyx_t_6 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_5);\n",
       "      if (likely(__pyx_t_6)) {\n",
       "        PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_5);\n",
       "        <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_6);\n",
       "        <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
       "        <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_5, function);\n",
       "      }\n",
       "    }\n",
       "    __pyx_t_4 = (__pyx_t_6) ? <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_5, __pyx_t_6) : <span class='pyx_c_api'>__Pyx_PyObject_CallNoArg</span>(__pyx_t_5);\n",
       "    <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    if (unlikely(!__pyx_t_4)) <span class='error_goto'>__PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    __pyx_t_8 = __pyx_<span class='py_c_api'>PyFloat_AsFloat</span>(__pyx_t_4); if (unlikely((__pyx_t_8 == (float)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    __pyx_v_x = __pyx_t_7;\n",
       "    __pyx_v_y = __pyx_t_8;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">7</span>:         <span class=\"k\">if</span> <span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">**</span> <span class=\"mf\">2</span> <span class=\"o\">+</span> <span class=\"n\">y</span> <span class=\"o\">**</span> <span class=\"mf\">2</span><span class=\"p\">)</span> <span class=\"o\">**</span> <span class=\"mf\">0.5</span> <span class=\"o\">&lt;=</span> <span class=\"mf\">1</span><span class=\"p\">:</span></pre>\n",
       "<pre class='cython code score-0 '>    __pyx_t_9 = ((pow(((double)(powf(__pyx_v_x, 2.0) + powf(__pyx_v_y, 2.0))), 0.5) &lt;= 1.0) != 0);\n",
       "    if (__pyx_t_9) {\n",
       "/* … */\n",
       "    }\n",
       "  }\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">8</span>:             <span class=\"n\">circle</span> <span class=\"o\">+=</span> <span class=\"mf\">1</span></pre>\n",
       "<pre class='cython code score-0 '>      __pyx_v_circle = (__pyx_v_circle + 1);\n",
       "</pre><pre class=\"cython line score-11\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">9</span>:     <span class=\"k\">return</span> <span class=\"p\">(</span><span class=\"mf\">4</span> <span class=\"o\">*</span> <span class=\"n\">circle</span><span class=\"p\">)</span> <span class=\"o\">/</span> <span class=\"n\">n</span></pre>\n",
       "<pre class='cython code score-11 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  __pyx_t_10 = (4 * __pyx_v_circle);\n",
       "  if (unlikely(__pyx_v_n == 0)) {\n",
       "    <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "    <span class='error_goto'>__PYX_ERR(0, 9, __pyx_L1_error)</span>\n",
       "  }\n",
       "  __pyx_t_4 = <span class='py_c_api'>PyFloat_FromDouble</span>((((double)__pyx_t_10) / ((double)__pyx_v_n)));<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 9, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "  __pyx_r = __pyx_t_4;\n",
       "  __pyx_t_4 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "import random\n",
    "def mcs_pi_cy1(int n):\n",
    "    cdef int i, circle = 0\n",
    "    cdef float x, y\n",
    "    for i in range(n):\n",
    "        x, y = random.random(), random.random()\n",
    "        if (x ** 2 + y ** 2) ** 0.5 <= 1:\n",
    "            circle += 1\n",
    "    return (4 * circle) / n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 902 ms, sys: 11.2 ms, total: 913 ms\n",
      "Wall time: 912 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3.1420408"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time mcs_pi_cy1(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_adff47949fdcd4d082aff786c3571dc7.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython  { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-0\">&#xA0;<span class=\"\">01</span>: <span class=\"k\">from</span> <span class=\"nn\">libc.stdlib</span> <span class=\"k\">cimport</span> <span class=\"n\">rand</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">02</span>: <span class=\"k\">cdef</span> <span class=\"kr\">extern</span> <span class=\"k\">from</span> <span class=\"s\">&#39;limits.h&#39;</span><span class=\"p\">:</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">03</span>:     <span class=\"nb\">int</span> <span class=\"n\">INT_MAX</span></pre>\n",
       "<pre class=\"cython line score-23\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">04</span>: <span class=\"k\">def</span> <span class=\"nf\">mcs_pi_cy2</span><span class=\"p\">(</span><span class=\"nb\">int</span> <span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-23 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_adff47949fdcd4d082aff786c3571dc7_1mcs_pi_cy2(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_adff47949fdcd4d082aff786c3571dc7_1mcs_pi_cy2 = {\"mcs_pi_cy2\", (PyCFunction)__pyx_pw_46_cython_magic_adff47949fdcd4d082aff786c3571dc7_1mcs_pi_cy2, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_adff47949fdcd4d082aff786c3571dc7_1mcs_pi_cy2(PyObject *__pyx_self, PyObject *__pyx_arg_n) {\n",
       "  int __pyx_v_n;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"mcs_pi_cy2 (wrapper)\", 0);\n",
       "  assert(__pyx_arg_n); {\n",
       "    __pyx_v_n = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(__pyx_arg_n); if (unlikely((__pyx_v_n == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L3_error)</span>\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_adff47949fdcd4d082aff786c3571dc7.mcs_pi_cy2\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_adff47949fdcd4d082aff786c3571dc7_mcs_pi_cy2(__pyx_self, ((int)__pyx_v_n));\n",
       "\n",
       "  /* function exit code */\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_adff47949fdcd4d082aff786c3571dc7_mcs_pi_cy2(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_n) {\n",
       "  CYTHON_UNUSED int __pyx_v_i;\n",
       "  int __pyx_v_circle;\n",
       "  float __pyx_v_x;\n",
       "  float __pyx_v_y;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"mcs_pi_cy2\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_9);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_adff47949fdcd4d082aff786c3571dc7.mcs_pi_cy2\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple_ = <span class='py_c_api'>PyTuple_Pack</span>(6, __pyx_n_s_n, __pyx_n_s_n, __pyx_n_s_i, __pyx_n_s_circle, __pyx_n_s_x, __pyx_n_s_y);<span class='error_goto'> if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 4, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple_);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple_);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_adff47949fdcd4d082aff786c3571dc7_1mcs_pi_cy2, NULL, __pyx_n_s_cython_magic_adff47949fdcd4d082);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_mcs_pi_cy2, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">05</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span><span class=\"p\">,</span> <span class=\"nf\">circle</span> <span class=\"o\">=</span> <span class=\"mf\">0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_circle = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">06</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">x</span><span class=\"p\">,</span> <span class=\"nf\">y</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">07</span>:     <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_1 = __pyx_v_n;\n",
       "  __pyx_t_2 = __pyx_t_1;\n",
       "  for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n",
       "    __pyx_v_i = __pyx_t_3;\n",
       "</pre><pre class=\"cython line score-10\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">08</span>:         <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"o\">=</span> <span class=\"n\">rand</span><span class=\"p\">()</span> <span class=\"o\">/</span> <span class=\"n\">INT_MAX</span><span class=\"p\">,</span> <span class=\"n\">rand</span><span class=\"p\">()</span> <span class=\"o\">/</span> <span class=\"n\">INT_MAX</span></pre>\n",
       "<pre class='cython code score-10 '>    __pyx_t_4 = rand();\n",
       "    if (unlikely(INT_MAX == 0)) {\n",
       "      <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "      <span class='error_goto'>__PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "    }\n",
       "    __pyx_t_5 = (((double)__pyx_t_4) / ((double)INT_MAX));\n",
       "    __pyx_t_4 = rand();\n",
       "    if (unlikely(INT_MAX == 0)) {\n",
       "      <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "      <span class='error_goto'>__PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "    }\n",
       "    __pyx_t_6 = (((double)__pyx_t_4) / ((double)INT_MAX));\n",
       "    __pyx_v_x = __pyx_t_5;\n",
       "    __pyx_v_y = __pyx_t_6;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">09</span>:         <span class=\"k\">if</span> <span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">**</span> <span class=\"mf\">2</span> <span class=\"o\">+</span> <span class=\"n\">y</span> <span class=\"o\">**</span> <span class=\"mf\">2</span><span class=\"p\">)</span> <span class=\"o\">**</span> <span class=\"mf\">0.5</span> <span class=\"o\">&lt;=</span> <span class=\"mf\">1</span><span class=\"p\">:</span></pre>\n",
       "<pre class='cython code score-0 '>    __pyx_t_7 = ((pow(((double)(powf(__pyx_v_x, 2.0) + powf(__pyx_v_y, 2.0))), 0.5) &lt;= 1.0) != 0);\n",
       "    if (__pyx_t_7) {\n",
       "/* … */\n",
       "    }\n",
       "  }\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">10</span>:             <span class=\"n\">circle</span> <span class=\"o\">+=</span> <span class=\"mf\">1</span></pre>\n",
       "<pre class='cython code score-0 '>      __pyx_v_circle = (__pyx_v_circle + 1);\n",
       "</pre><pre class=\"cython line score-11\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">11</span>:     <span class=\"k\">return</span> <span class=\"p\">(</span><span class=\"mf\">4</span> <span class=\"o\">*</span> <span class=\"n\">circle</span><span class=\"p\">)</span> <span class=\"o\">/</span> <span class=\"n\">n</span></pre>\n",
       "<pre class='cython code score-11 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  __pyx_t_8 = (4 * __pyx_v_circle);\n",
       "  if (unlikely(__pyx_v_n == 0)) {\n",
       "    <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "    <span class='error_goto'>__PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  }\n",
       "  __pyx_t_9 = <span class='py_c_api'>PyFloat_FromDouble</span>((((double)__pyx_t_8) / ((double)__pyx_v_n)));<span class='error_goto'> if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
       "  __pyx_r = __pyx_t_9;\n",
       "  __pyx_t_9 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "from libc.stdlib cimport rand\n",
    "cdef extern from 'limits.h':\n",
    "    int INT_MAX\n",
    "def mcs_pi_cy2(int n):\n",
    "    cdef int i, circle = 0\n",
    "    cdef float x, y\n",
    "    for i in range(n):\n",
    "        x, y = rand() / INT_MAX, rand() / INT_MAX\n",
    "        if (x ** 2 + y ** 2) ** 0.5 <= 1:\n",
    "            circle += 1\n",
    "    return (4 * circle) / n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 130 ms, sys: 1.41 ms, total: 132 ms\n",
      "Wall time: 132 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3.1419388"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time mcs_pi_cy2(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Binomial Trees"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [],
   "source": [
    "S0 = 36.  \n",
    "T = 1.0  \n",
    "r = 0.06  \n",
    "sigma = 0.2  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [],
   "source": [
    "def simulate_tree(M):\n",
    "    dt = T / M  \n",
    "    u = math.exp(sigma * math.sqrt(dt))  \n",
    "    d = 1 / u  \n",
    "    S = np.zeros((M + 1, M + 1))\n",
    "    S[0, 0] = S0\n",
    "    z = 1\n",
    "    for t in range(1, M + 1):\n",
    "        for i in range(z):\n",
    "            S[i, t] = S[i, t-1] * u\n",
    "            S[i+1, t] = S[i, t-1] * d\n",
    "        z += 1\n",
    "    return S"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.set_printoptions(formatter={'float':\n",
    "                               lambda x: '%6.2f' % x})  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  39.79,  43.97,  48.59,  53.71],\n",
       "       [  0.00,  32.57,  36.00,  39.79,  43.97],\n",
       "       [  0.00,   0.00,  29.47,  32.57,  36.00],\n",
       "       [  0.00,   0.00,   0.00,  26.67,  29.47],\n",
       "       [  0.00,   0.00,   0.00,   0.00,  24.13]])"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simulate_tree(4)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 106 ms, sys: 3.1 ms, total: 109 ms\n",
      "Wall time: 109 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  36.32,  36.65, ..., 3095.69, 3123.50, 3151.57],\n",
       "       [  0.00,  35.68,  36.00, ..., 3040.81, 3068.13, 3095.69],\n",
       "       [  0.00,   0.00,  35.36, ..., 2986.89, 3013.73, 3040.81],\n",
       "       ...,\n",
       "       [  0.00,   0.00,   0.00, ...,   0.42,   0.42,   0.43],\n",
       "       [  0.00,   0.00,   0.00, ...,   0.00,   0.41,   0.42],\n",
       "       [  0.00,   0.00,   0.00, ...,   0.00,   0.00,   0.41]])"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time simulate_tree(500)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "M = 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2, 3, 4],\n",
       "       [0, 1, 2, 3, 4],\n",
       "       [0, 1, 2, 3, 4],\n",
       "       [0, 1, 2, 3, 4],\n",
       "       [0, 1, 2, 3, 4]])"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "up = np.arange(M + 1)\n",
    "up = np.resize(up, (M + 1, M + 1))  \n",
    "up"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0, 0, 0],\n",
       "       [2, 2, 2, 2, 2],\n",
       "       [4, 4, 4, 4, 4],\n",
       "       [6, 6, 6, 6, 6],\n",
       "       [8, 8, 8, 8, 8]])"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "down = up.T * 2  \n",
    "down"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4],\n",
       "       [-2, -1,  0,  1,  2],\n",
       "       [-4, -3, -2, -1,  0],\n",
       "       [-6, -5, -4, -3, -2],\n",
       "       [-8, -7, -6, -5, -4]])"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "up - down  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [],
   "source": [
    "dt = T / M"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  39.79,  43.97,  48.59,  53.71],\n",
       "       [ 29.47,  32.57,  36.00,  39.79,  43.97],\n",
       "       [ 24.13,  26.67,  29.47,  32.57,  36.00],\n",
       "       [ 19.76,  21.84,  24.13,  26.67,  29.47],\n",
       "       [ 16.18,  17.88,  19.76,  21.84,  24.13]])"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S0 * np.exp(sigma * math.sqrt(dt) * (up - down))  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [],
   "source": [
    "def simulate_tree_np(M):\n",
    "    dt = T / M\n",
    "    up = np.arange(M + 1)\n",
    "    up = np.resize(up, (M + 1, M + 1))\n",
    "    down = up.transpose() * 2\n",
    "    S = S0 * np.exp(sigma * math.sqrt(dt) * (up - down))\n",
    "    return S"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  39.79,  43.97,  48.59,  53.71],\n",
       "       [ 29.47,  32.57,  36.00,  39.79,  43.97],\n",
       "       [ 24.13,  26.67,  29.47,  32.57,  36.00],\n",
       "       [ 19.76,  21.84,  24.13,  26.67,  29.47],\n",
       "       [ 16.18,  17.88,  19.76,  21.84,  24.13]])"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simulate_tree_np(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 5.36 ms, sys: 3.3 ms, total: 8.67 ms\n",
      "Wall time: 6.36 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  36.32,  36.65, ..., 3095.69, 3123.50, 3151.57],\n",
       "       [ 35.36,  35.68,  36.00, ..., 3040.81, 3068.13, 3095.69],\n",
       "       [ 34.73,  35.05,  35.36, ..., 2986.89, 3013.73, 3040.81],\n",
       "       ...,\n",
       "       [  0.00,   0.00,   0.00, ...,   0.42,   0.42,   0.43],\n",
       "       [  0.00,   0.00,   0.00, ...,   0.41,   0.41,   0.42],\n",
       "       [  0.00,   0.00,   0.00, ...,   0.40,   0.41,   0.41]])"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time simulate_tree_np(500)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numba"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [],
   "source": [
    "simulate_tree_nb = numba.jit(simulate_tree)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  39.79,  43.97,  48.59,  53.71],\n",
       "       [  0.00,  32.57,  36.00,  39.79,  43.97],\n",
       "       [  0.00,   0.00,  29.47,  32.57,  36.00],\n",
       "       [  0.00,   0.00,   0.00,  26.67,  29.47],\n",
       "       [  0.00,   0.00,   0.00,   0.00,  24.13]])"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simulate_tree_nb(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 430 µs, sys: 1e+03 ns, total: 431 µs\n",
      "Wall time: 435 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  36.32,  36.65, ..., 3095.69, 3123.50, 3151.57],\n",
       "       [  0.00,  35.68,  36.00, ..., 3040.81, 3068.13, 3095.69],\n",
       "       [  0.00,   0.00,  35.36, ..., 2986.89, 3013.73, 3040.81],\n",
       "       ...,\n",
       "       [  0.00,   0.00,   0.00, ...,   0.42,   0.42,   0.43],\n",
       "       [  0.00,   0.00,   0.00, ...,   0.00,   0.41,   0.42],\n",
       "       [  0.00,   0.00,   0.00, ...,   0.00,   0.00,   0.41]])"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time simulate_tree_nb(500)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "298 µs ± 4.79 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit simulate_tree_nb(500)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cython"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_5edae46bb54cbe088ba0629c1aa30e21.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython  { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-16\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">01</span>: <span class=\"k\">import</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">np</span></pre>\n",
       "<pre class='cython code score-16 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_Import</span>(__pyx_n_s_numpy, 0, 0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_np, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 1, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "/* … */\n",
       "  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyDict_NewPresized</span>(0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 1, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">02</span>: <span class=\"k\">cimport</span> <span class=\"nn\">cython</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">03</span>: <span class=\"k\">from</span> <span class=\"nn\">libc.math</span> <span class=\"k\">cimport</span> <span class=\"n\">exp</span><span class=\"p\">,</span> <span class=\"n\">sqrt</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">04</span>: <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">S0</span> <span class=\"o\">=</span> <span class=\"mf\">36.</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_S0 = 36.;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">05</span>: <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">T</span> <span class=\"o\">=</span> <span class=\"mf\">1.0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_T = 1.0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">06</span>: <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">r</span> <span class=\"o\">=</span> <span class=\"mf\">0.06</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_r = 0.06;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">07</span>: <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">sigma</span> <span class=\"o\">=</span> <span class=\"mf\">0.2</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_sigma = 0.2;\n",
       "</pre><pre class=\"cython line score-29\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">08</span>: <span class=\"k\">def</span> <span class=\"nf\">simulate_tree_cy</span><span class=\"p\">(</span><span class=\"nb\">int</span> <span class=\"n\">M</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-29 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_1simulate_tree_cy(PyObject *__pyx_self, PyObject *__pyx_arg_M); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_1simulate_tree_cy = {\"simulate_tree_cy\", (PyCFunction)__pyx_pw_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_1simulate_tree_cy, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_1simulate_tree_cy(PyObject *__pyx_self, PyObject *__pyx_arg_M) {\n",
       "  int __pyx_v_M;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"simulate_tree_cy (wrapper)\", 0);\n",
       "  assert(__pyx_arg_M); {\n",
       "    __pyx_v_M = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(__pyx_arg_M); if (unlikely((__pyx_v_M == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 8, __pyx_L3_error)</span>\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_5edae46bb54cbe088ba0629c1aa30e21.simulate_tree_cy\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_simulate_tree_cy(__pyx_self, ((int)__pyx_v_M));\n",
       "\n",
       "  /* function exit code */\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_simulate_tree_cy(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_M) {\n",
       "  int __pyx_v_z;\n",
       "  int __pyx_v_t;\n",
       "  int __pyx_v_i;\n",
       "  float __pyx_v_dt;\n",
       "  float __pyx_v_u;\n",
       "  float __pyx_v_d;\n",
       "  __Pyx_memviewslice __pyx_v_S = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"simulate_tree_cy\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_1);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_3);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5);\n",
       "  __PYX_XDEC_MEMVIEW(&amp;__pyx_t_6, 1);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_5edae46bb54cbe088ba0629c1aa30e21.simulate_tree_cy\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __PYX_XDEC_MEMVIEW(&amp;__pyx_v_S, 1);\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__19 = <span class='py_c_api'>PyTuple_Pack</span>(9, __pyx_n_s_M, __pyx_n_s_M, __pyx_n_s_z, __pyx_n_s_t, __pyx_n_s_i, __pyx_n_s_dt, __pyx_n_s_u, __pyx_n_s_d, __pyx_n_s_S);<span class='error_goto'> if (unlikely(!__pyx_tuple__19)) __PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__19);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__19);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_1simulate_tree_cy, NULL, __pyx_n_s_cython_magic_5edae46bb54cbe088b);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_simulate_tree_cy, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_codeobj__20 = (PyObject*)<span class='pyx_c_api'>__Pyx_PyCode_New</span>(1, 0, 9, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__19, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_yves_ipython_cython__cyth, __pyx_n_s_simulate_tree_cy, 8, __pyx_empty_bytes);<span class='error_goto'> if (unlikely(!__pyx_codeobj__20)) __PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">09</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">z</span><span class=\"p\">,</span> <span class=\"nf\">t</span><span class=\"p\">,</span> <span class=\"nf\">i</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">10</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">float</span> <span class=\"nf\">dt</span><span class=\"p\">,</span> <span class=\"nf\">u</span><span class=\"p\">,</span> <span class=\"nf\">d</span></pre>\n",
       "<pre class=\"cython line score-30\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">11</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">float</span>[<span class=\"p\">:,</span> <span class=\"p\">:]</span> <span class=\"n\">S</span> <span class=\"o\">=</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">zeros</span><span class=\"p\">((</span><span class=\"n\">M</span> <span class=\"o\">+</span> <span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">M</span> <span class=\"o\">+</span> <span class=\"mf\">1</span><span class=\"p\">),</span></pre>\n",
       "<pre class='cython code score-30 '>  <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_1, __pyx_n_s_np);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_1, __pyx_n_s_zeros);<span class='error_goto'> if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyInt_From_long</span>((__pyx_v_M + 1));<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyInt_From_long</span>((__pyx_v_M + 1));<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
       "  __pyx_t_4 = <span class='py_c_api'>PyTuple_New</span>(2);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_1);\n",
       "  <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 0, __pyx_t_1);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_3);\n",
       "  <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 1, __pyx_t_3);\n",
       "  __pyx_t_1 = 0;\n",
       "  __pyx_t_3 = 0;\n",
       "  __pyx_t_3 = <span class='py_c_api'>PyTuple_New</span>(1);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_4);\n",
       "  <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_3, 0, __pyx_t_4);\n",
       "  __pyx_t_4 = 0;\n",
       "/* … */\n",
       "  __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_t_2, __pyx_t_3, __pyx_t_4);<span class='error_goto'> if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  __pyx_t_6 = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_dsds_float</span>(__pyx_t_5, PyBUF_WRITABLE);<span class='error_goto'> if (unlikely(!__pyx_t_6.memview)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_v_S = __pyx_t_6;\n",
       "  __pyx_t_6.memview = NULL;\n",
       "  __pyx_t_6.data = NULL;\n",
       "</pre><pre class=\"cython line score-13\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">12</span>:                                   <span class=\"n\">dtype</span><span class=\"o\">=</span><span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">float32</span><span class=\"p\">)</span></pre>\n",
       "<pre class='cython code score-13 '>  __pyx_t_4 = <span class='pyx_c_api'>__Pyx_PyDict_NewPresized</span>(1);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 12, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "  <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_1, __pyx_n_s_np);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 12, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_1, __pyx_n_s_float32);<span class='error_goto'> if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 12, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_t_4, __pyx_n_s_dtype, __pyx_t_5) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 12, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "</pre><pre class=\"cython line score-5\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">13</span>:     <span class=\"n\">dt</span> <span class=\"o\">=</span> <span class=\"n\">T</span> <span class=\"o\">/</span> <span class=\"n\">M</span></pre>\n",
       "<pre class='cython code score-5 '>  if (unlikely(__pyx_v_M == 0)) {\n",
       "    <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "    <span class='error_goto'>__PYX_ERR(0, 13, __pyx_L1_error)</span>\n",
       "  }\n",
       "  __pyx_v_dt = (__pyx_v_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_T / ((float)__pyx_v_M));\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">14</span>:     <span class=\"n\">u</span> <span class=\"o\">=</span> <span class=\"n\">exp</span><span class=\"p\">(</span><span class=\"n\">sigma</span> <span class=\"o\">*</span> <span class=\"n\">sqrt</span><span class=\"p\">(</span><span class=\"n\">dt</span><span class=\"p\">))</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_u = exp((__pyx_v_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_sigma * sqrt(__pyx_v_dt)));\n",
       "</pre><pre class=\"cython line score-5\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">15</span>:     <span class=\"n\">d</span> <span class=\"o\">=</span> <span class=\"mf\">1</span> <span class=\"o\">/</span> <span class=\"n\">u</span></pre>\n",
       "<pre class='cython code score-5 '>  if (unlikely(__pyx_v_u == 0)) {\n",
       "    <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"float division\");\n",
       "    <span class='error_goto'>__PYX_ERR(0, 15, __pyx_L1_error)</span>\n",
       "  }\n",
       "  __pyx_v_d = (1.0 / __pyx_v_u);\n",
       "</pre><pre class=\"cython line score-2\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">16</span>:     <span class=\"n\">S</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">,</span> <span class=\"mf\">0</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">S0</span></pre>\n",
       "<pre class='cython code score-2 '>  __pyx_t_7 = 0;\n",
       "  __pyx_t_8 = 0;\n",
       "  __pyx_t_9 = -1;\n",
       "  if (__pyx_t_7 &lt; 0) {\n",
       "    __pyx_t_7 += __pyx_v_S.shape[0];\n",
       "    if (unlikely(__pyx_t_7 &lt; 0)) __pyx_t_9 = 0;\n",
       "  } else if (unlikely(__pyx_t_7 &gt;= __pyx_v_S.shape[0])) __pyx_t_9 = 0;\n",
       "  if (__pyx_t_8 &lt; 0) {\n",
       "    __pyx_t_8 += __pyx_v_S.shape[1];\n",
       "    if (unlikely(__pyx_t_8 &lt; 0)) __pyx_t_9 = 1;\n",
       "  } else if (unlikely(__pyx_t_8 &gt;= __pyx_v_S.shape[1])) __pyx_t_9 = 1;\n",
       "  if (unlikely(__pyx_t_9 != -1)) {\n",
       "    <span class='pyx_c_api'>__Pyx_RaiseBufferIndexError</span>(__pyx_t_9);\n",
       "    <span class='error_goto'>__PYX_ERR(0, 16, __pyx_L1_error)</span>\n",
       "  }\n",
       "  *((float *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_S.data + __pyx_t_7 * __pyx_v_S.strides[0]) ) + __pyx_t_8 * __pyx_v_S.strides[1]) )) = __pyx_v_46_cython_magic_5edae46bb54cbe088ba0629c1aa30e21_S0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">17</span>:     <span class=\"n\">z</span> <span class=\"o\">=</span> <span class=\"mf\">1</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_z = 1;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">18</span>:     <span class=\"k\">for</span> <span class=\"n\">t</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">M</span> <span class=\"o\">+</span> <span class=\"mf\">1</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_10 = (__pyx_v_M + 1);\n",
       "  __pyx_t_11 = __pyx_t_10;\n",
       "  for (__pyx_t_9 = 1; __pyx_t_9 &lt; __pyx_t_11; __pyx_t_9+=1) {\n",
       "    __pyx_v_t = __pyx_t_9;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">19</span>:         <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">z</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>    __pyx_t_12 = __pyx_v_z;\n",
       "    __pyx_t_13 = __pyx_t_12;\n",
       "    for (__pyx_t_14 = 0; __pyx_t_14 &lt; __pyx_t_13; __pyx_t_14+=1) {\n",
       "      __pyx_v_i = __pyx_t_14;\n",
       "</pre><pre class=\"cython line score-4\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">20</span>:             <span class=\"n\">S</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">S</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"o\">*</span> <span class=\"n\">u</span></pre>\n",
       "<pre class='cython code score-4 '>      __pyx_t_15 = __pyx_v_i;\n",
       "      __pyx_t_16 = (__pyx_v_t - 1);\n",
       "      __pyx_t_17 = -1;\n",
       "      if (__pyx_t_15 &lt; 0) {\n",
       "        __pyx_t_15 += __pyx_v_S.shape[0];\n",
       "        if (unlikely(__pyx_t_15 &lt; 0)) __pyx_t_17 = 0;\n",
       "      } else if (unlikely(__pyx_t_15 &gt;= __pyx_v_S.shape[0])) __pyx_t_17 = 0;\n",
       "      if (__pyx_t_16 &lt; 0) {\n",
       "        __pyx_t_16 += __pyx_v_S.shape[1];\n",
       "        if (unlikely(__pyx_t_16 &lt; 0)) __pyx_t_17 = 1;\n",
       "      } else if (unlikely(__pyx_t_16 &gt;= __pyx_v_S.shape[1])) __pyx_t_17 = 1;\n",
       "      if (unlikely(__pyx_t_17 != -1)) {\n",
       "        <span class='pyx_c_api'>__Pyx_RaiseBufferIndexError</span>(__pyx_t_17);\n",
       "        <span class='error_goto'>__PYX_ERR(0, 20, __pyx_L1_error)</span>\n",
       "      }\n",
       "      __pyx_t_18 = __pyx_v_i;\n",
       "      __pyx_t_19 = __pyx_v_t;\n",
       "      __pyx_t_17 = -1;\n",
       "      if (__pyx_t_18 &lt; 0) {\n",
       "        __pyx_t_18 += __pyx_v_S.shape[0];\n",
       "        if (unlikely(__pyx_t_18 &lt; 0)) __pyx_t_17 = 0;\n",
       "      } else if (unlikely(__pyx_t_18 &gt;= __pyx_v_S.shape[0])) __pyx_t_17 = 0;\n",
       "      if (__pyx_t_19 &lt; 0) {\n",
       "        __pyx_t_19 += __pyx_v_S.shape[1];\n",
       "        if (unlikely(__pyx_t_19 &lt; 0)) __pyx_t_17 = 1;\n",
       "      } else if (unlikely(__pyx_t_19 &gt;= __pyx_v_S.shape[1])) __pyx_t_17 = 1;\n",
       "      if (unlikely(__pyx_t_17 != -1)) {\n",
       "        <span class='pyx_c_api'>__Pyx_RaiseBufferIndexError</span>(__pyx_t_17);\n",
       "        <span class='error_goto'>__PYX_ERR(0, 20, __pyx_L1_error)</span>\n",
       "      }\n",
       "      *((float *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_S.data + __pyx_t_18 * __pyx_v_S.strides[0]) ) + __pyx_t_19 * __pyx_v_S.strides[1]) )) = ((*((float *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_S.data + __pyx_t_15 * __pyx_v_S.strides[0]) ) + __pyx_t_16 * __pyx_v_S.strides[1]) ))) * __pyx_v_u);\n",
       "</pre><pre class=\"cython line score-4\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">21</span>:             <span class=\"n\">S</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">S</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"o\">*</span> <span class=\"n\">d</span></pre>\n",
       "<pre class='cython code score-4 '>      __pyx_t_20 = __pyx_v_i;\n",
       "      __pyx_t_21 = (__pyx_v_t - 1);\n",
       "      __pyx_t_17 = -1;\n",
       "      if (__pyx_t_20 &lt; 0) {\n",
       "        __pyx_t_20 += __pyx_v_S.shape[0];\n",
       "        if (unlikely(__pyx_t_20 &lt; 0)) __pyx_t_17 = 0;\n",
       "      } else if (unlikely(__pyx_t_20 &gt;= __pyx_v_S.shape[0])) __pyx_t_17 = 0;\n",
       "      if (__pyx_t_21 &lt; 0) {\n",
       "        __pyx_t_21 += __pyx_v_S.shape[1];\n",
       "        if (unlikely(__pyx_t_21 &lt; 0)) __pyx_t_17 = 1;\n",
       "      } else if (unlikely(__pyx_t_21 &gt;= __pyx_v_S.shape[1])) __pyx_t_17 = 1;\n",
       "      if (unlikely(__pyx_t_17 != -1)) {\n",
       "        <span class='pyx_c_api'>__Pyx_RaiseBufferIndexError</span>(__pyx_t_17);\n",
       "        <span class='error_goto'>__PYX_ERR(0, 21, __pyx_L1_error)</span>\n",
       "      }\n",
       "      __pyx_t_22 = (__pyx_v_i + 1);\n",
       "      __pyx_t_23 = __pyx_v_t;\n",
       "      __pyx_t_17 = -1;\n",
       "      if (__pyx_t_22 &lt; 0) {\n",
       "        __pyx_t_22 += __pyx_v_S.shape[0];\n",
       "        if (unlikely(__pyx_t_22 &lt; 0)) __pyx_t_17 = 0;\n",
       "      } else if (unlikely(__pyx_t_22 &gt;= __pyx_v_S.shape[0])) __pyx_t_17 = 0;\n",
       "      if (__pyx_t_23 &lt; 0) {\n",
       "        __pyx_t_23 += __pyx_v_S.shape[1];\n",
       "        if (unlikely(__pyx_t_23 &lt; 0)) __pyx_t_17 = 1;\n",
       "      } else if (unlikely(__pyx_t_23 &gt;= __pyx_v_S.shape[1])) __pyx_t_17 = 1;\n",
       "      if (unlikely(__pyx_t_17 != -1)) {\n",
       "        <span class='pyx_c_api'>__Pyx_RaiseBufferIndexError</span>(__pyx_t_17);\n",
       "        <span class='error_goto'>__PYX_ERR(0, 21, __pyx_L1_error)</span>\n",
       "      }\n",
       "      *((float *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_S.data + __pyx_t_22 * __pyx_v_S.strides[0]) ) + __pyx_t_23 * __pyx_v_S.strides[1]) )) = ((*((float *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_S.data + __pyx_t_20 * __pyx_v_S.strides[0]) ) + __pyx_t_21 * __pyx_v_S.strides[1]) ))) * __pyx_v_d);\n",
       "    }\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">22</span>:         <span class=\"n\">z</span> <span class=\"o\">+=</span> <span class=\"mf\">1</span></pre>\n",
       "<pre class='cython code score-0 '>    __pyx_v_z = (__pyx_v_z + 1);\n",
       "  }\n",
       "</pre><pre class=\"cython line score-21\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">23</span>:     <span class=\"k\">return</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">array</span><span class=\"p\">(</span><span class=\"n\">S</span><span class=\"p\">)</span></pre>\n",
       "<pre class='cython code score-21 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_4, __pyx_n_s_np);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 23, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "  __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_4, __pyx_n_s_array);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 23, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  __pyx_t_4 = __pyx_memoryview_fromslice(__pyx_v_S, 2, (PyObject *(*)(char *)) __pyx_memview_get_float, (int (*)(char *, PyObject *)) __pyx_memview_set_float, 0);;<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 23, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "  __pyx_t_2 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_3))) {\n",
       "    __pyx_t_2 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_3);\n",
       "    if (likely(__pyx_t_2)) {\n",
       "      PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_3);\n",
       "      <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_2);\n",
       "      <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
       "      <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_3, function);\n",
       "    }\n",
       "  }\n",
       "  __pyx_t_5 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_t_4) : <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_3, __pyx_t_4);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  if (unlikely(!__pyx_t_5)) <span class='error_goto'>__PYX_ERR(0, 23, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __pyx_r = __pyx_t_5;\n",
       "  __pyx_t_5 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "import numpy as np\n",
    "cimport cython\n",
    "from libc.math cimport exp, sqrt\n",
    "cdef float S0 = 36.\n",
    "cdef float T = 1.0\n",
    "cdef float r = 0.06\n",
    "cdef float sigma = 0.2\n",
    "def simulate_tree_cy(int M):\n",
    "    cdef int z, t, i\n",
    "    cdef float dt, u, d\n",
    "    cdef float[:, :] S = np.zeros((M + 1, M + 1),\n",
    "                                  dtype=np.float32)  \n",
    "    dt = T / M\n",
    "    u = exp(sigma * sqrt(dt))\n",
    "    d = 1 / u\n",
    "    S[0, 0] = S0\n",
    "    z = 1\n",
    "    for t in range(1, M + 1):\n",
    "        for i in range(z):\n",
    "            S[i, t] = S[i, t-1] * u\n",
    "            S[i+1, t] = S[i, t-1] * d\n",
    "        z += 1\n",
    "    return np.array(S)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  39.79,  43.97,  48.59,  53.71],\n",
       "       [  0.00,  32.57,  36.00,  39.79,  43.97],\n",
       "       [  0.00,   0.00,  29.47,  32.57,  36.00],\n",
       "       [  0.00,   0.00,   0.00,  26.67,  29.47],\n",
       "       [  0.00,   0.00,   0.00,   0.00,  24.13]], dtype=float32)"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simulate_tree_cy(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.42 ms, sys: 1.25 ms, total: 2.67 ms\n",
      "Wall time: 1.38 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[ 36.00,  36.32,  36.65, ..., 3095.77, 3123.59, 3151.65],\n",
       "       [  0.00,  35.68,  36.00, ..., 3040.89, 3068.21, 3095.77],\n",
       "       [  0.00,   0.00,  35.36, ..., 2986.97, 3013.81, 3040.89],\n",
       "       ...,\n",
       "       [  0.00,   0.00,   0.00, ...,   0.42,   0.42,   0.43],\n",
       "       [  0.00,   0.00,   0.00, ...,   0.00,   0.41,   0.42],\n",
       "       [  0.00,   0.00,   0.00, ...,   0.00,   0.00,   0.41]],\n",
       "      dtype=float32)"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time simulate_tree_cy(500)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "248 µs ± 4.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit S = simulate_tree_cy(500)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Monte Carlo Simulation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "metadata": {},
   "outputs": [],
   "source": [
    "M = 100  \n",
    "I = 50000  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mcs_simulation_py(p):\n",
    "    M, I = p\n",
    "    dt = T / M\n",
    "    S = np.zeros((M + 1, I))\n",
    "    S[0] = S0\n",
    "    rn = np.random.standard_normal(S.shape)  \n",
    "    for t in range(1, M + 1):  \n",
    "        for i in range(I):  \n",
    "            S[t, i] = S[t-1, i] * math.exp((r - sigma ** 2 / 2) * dt +\n",
    "                                         sigma * math.sqrt(dt) * rn[t, i])  \n",
    "    return S      "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 6.35 s, sys: 37 ms, total: 6.39 s\n",
      "Wall time: 6.39 s\n"
     ]
    }
   ],
   "source": [
    "%time S = mcs_simulation_py((M, I))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38.25315828072039"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S[-1].mean()  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38.22611567563295"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S0 * math.exp(r * T)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {},
   "outputs": [],
   "source": [
    "K = 40.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [],
   "source": [
    "C0 = math.exp(-r * T) * np.maximum(K - S[-1], 0).mean()  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.8309142786243937"
      ]
     },
     "execution_count": 125,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C0  #  <8>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x632050240>"
      ]
     },
     "execution_count": 126,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAl0AAAFkCAYAAAAaH47TAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvDW2N/gAAIABJREFUeJzt3XuYXuO9//F3TiRhRiY1BKEqiS+KHvRA2TROQVD0sEsVDemmrVY1trCdqkqiWj3Qze+HXS7dtDvaOkRFW9Rmh6iNOtS3JI5VSVQiiSBo9h/PGh1mkhnJ5J4xz/t1Xb3Mcz9rrede365n8pl7rXWvPkuXLkWSJEmrVt/u7oAkSVI9MHRJkiQVYOiSJEkqwNAlSZJUgKFLkiSpAEOXJElSAf27uwMdmTt34Tt+ToumpsHMm7e4u7vR4/T2ugzdZksAnr/7gU6v09trsqKsS1vWpH3WpS1r0r5VVZfm5oY+y3rPka4C+vfv191d6JGsS1vWpH3WpS1r0j7r0pY1aV931KVTI10REcCBwEvATsBpwBzgZOBRYGPgG5m5KCL6AmcCi4B3Axdn5h3VdnYFDqjWXZqZ3+zKnZEkSeqpOhzpioh+wPeA0zNzMnA48BhwAXBhZp4FPAAcX63yGaAxM8+o2i6LiH4RMbha5+uZeRqwdUTs0tU7JEmS1BN15vTih4E+wNERcQKwDzAfGA3cVS1zOzC2+nksMB0gM58HXgbeC2wHPJGZr7SzjiRJUq/WmdOL76YWmA7MzBci4nLgXcBLmdlykfsCYJ3q53WAha3Wb3mveRnty9XUNLhXnI9ubm7o7i70SL26Ln1r11K+3X3s1TVZCdalLWvSPuvSljVpX+m6dCZ0LQAezswXqte3Af8EDIqIPlXwaqR2nRbVf1vvRct7S5fRvly94Y6L5uYG5s5d2PGCdaa312Xo32t/kzz/Nvaxt9dkRVmXtqxJ+6xLW9akfauqLssLcp05vXgn8K7q2i6ojXw9CNxM7dQjwPbA1OrnqdRGxoiIocDAavnpwLsjYvV21pEkSerVOhzpysznI+J44PsRMZfaacLTgf8ETomI3YGNgGOrVX4OfCAiTq3aD8nM14HFEXEU8MNqO3/MzN91/S5JkiT1PJ2aMiIzfwn88i3NjwPj2ln27/zjTsa3vvcb4Ddvr4uSJEkr78c//gEPPfQg5533/7rl850cVZIk1YX99/90t35+j38MkCRJ6pw1TjuJ1a/91Zsb+/Z548aeFfHKPvvx4mlnLPP9qVOv4cILz+ezn/0cM2c+wvz5L7DXXvswY8Z0nn76Kc4++1zWWGNNZs2ayU9/eikjRozkiSce55BDxrHBBsP55S+n8NhjMxk69F08++xfmTDhBBYvXsxpp/0b/fr1ZcSIUTz44P3sttse7Lvv/m/67B/96HvccstNnHzy6QwfviGnnHICu+++ByNHBv/1X//JpptuxiOP/JkjjzyaYcOGvWndK664ggsuuJApU65lxow7OPvsb/OjH13Ieuutz3333cPUqdew8cbv4cknn+DII49myJAhK1zDFo50SZKkFTZ27L5stNG72XTTzTj55G+x2moDeOmlFznhhFMYNSq46647AZg8+Qz22++THHTQIYwZsxfnnfd9AJqb1+GYY47jsMOOYODAgcyYcQeNjY0cfPChLFiwgCOP/Aqnnz6JKVOubPPZX/rS1xgwYADDh2/Eu961NptsMpL99vsUgwYN4l/+5St87nOHMnr0Llx11c/arHvggQe+8fNHPrItw4atB8DSpUs59dQTGT/+KA466BC23vr9XHbZxV1SK0e6JEnqJV487Yw2o1LNzQ1va+qaFbXBBsMBWHPNBtZfv/ZzQ0MDixfXpn6aOfMRZsy4g3vvvYclS15h8OBBAAwcOJAf//iHrLXWEB577DE23XSzN7a54YYbAdDU1PTGdlrr168fe+/9Ca6++iq23HJrPvKRbQFYffXVueqqnzNkyBCeeeYZXnvt1U7vx/z581mwYAE33HA9AAsXvkDfvl0zX6ihS5IkrXIjR27KTjvtzMiRo1iyZAm33nozACeddDw/+ckVDBs2jMWLX3zTOn369Olwu/vssx9HHHEozz33HBMmTATg/PN/wI47fpw999ybGTPu4De/uaHddZcu/cdp1zlzZgMwZMgQhgwZwic+cQCNjY288MJ8Hnjg/hXa57cydEmtjJt00wqtd8nEnbu4J5L0znDXXXcwe/azXH/9teyww07MnPkI06Zdz9prN3Pfffcwa9ajbLvtx5g48WSuvPJy1ltvfebMmc3uu+8FwH77fZLvfW8yW2/9Ph544I88+eTjbLvtx5g27XpmznyEhx9+iFmzZrJo0SJuueV3fPzjb35s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\n",
      "text/plain": [
       "<Figure size 720x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10, 6))\n",
    "plt.hist(S[-1], bins=35, label='frequency')\n",
    "plt.axvline(S[-1].mean(), color='r', label='mean value')\n",
    "plt.legend(loc=0)\n",
    "# plt.savefig('../../images/ch10/perf_02.png');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mcs_simulation_np(p):\n",
    "    M, I = p\n",
    "    dt = T / M\n",
    "    S = np.zeros((M + 1, I))\n",
    "    S[0] = S0\n",
    "    rn = np.random.standard_normal(S.shape)\n",
    "    for t in range(1, M + 1):  \n",
    "        S[t] = S[t-1] * np.exp((r - sigma ** 2 / 2) * dt +\n",
    "                               sigma * math.sqrt(dt) * rn[t]) \n",
    "    return S      "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 273 ms, sys: 20.2 ms, total: 293 ms\n",
      "Wall time: 206 ms\n"
     ]
    }
   ],
   "source": [
    "%time S = mcs_simulation_np((M, I))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38.17244220811968"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S[-1].mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "191 ms ± 6.99 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit S = mcs_simulation_np((M, I))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numba "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "metadata": {},
   "outputs": [],
   "source": [
    "mcs_simulation_nb = numba.jit(mcs_simulation_py)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 977 ms, sys: 21.9 ms, total: 999 ms\n",
      "Wall time: 506 ms\n"
     ]
    }
   ],
   "source": [
    "%time S = mcs_simulation_nb((M, I))  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 190 ms, sys: 8.39 ms, total: 199 ms\n",
      "Wall time: 198 ms\n"
     ]
    }
   ],
   "source": [
    "%time S = mcs_simulation_nb((M, I))  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38.223313865317685"
      ]
     },
     "execution_count": 134,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S[-1].mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [],
   "source": [
    "C0 = math.exp(-r * T) * np.maximum(K - S[-1], 0).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.83789322158541"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "199 ms ± 2.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit S = mcs_simulation_nb((M, I))  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cython &mdash; Sequential"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%cython\n",
    "import numpy as np\n",
    "cimport numpy as np\n",
    "cimport cython\n",
    "from libc.math cimport exp, sqrt\n",
    "cdef float S0 = 36.\n",
    "cdef float T = 1.0\n",
    "cdef float r = 0.06\n",
    "cdef float sigma = 0.2\n",
    "@cython.boundscheck(False)\n",
    "@cython.wraparound(False)\n",
    "def mcs_simulation_cy(p):\n",
    "    cdef int M, I\n",
    "    M, I = p\n",
    "    cdef int t, i\n",
    "    cdef float dt = T / M\n",
    "    cdef double[:, :] S = np.zeros((M + 1, I))\n",
    "    cdef double[:, :] rn = np.random.standard_normal((M + 1, I))\n",
    "    S[0] = S0\n",
    "    for t in range(1, M + 1):\n",
    "        for i in range(I):\n",
    "            S[t, i] = S[t-1, i] * exp((r - sigma ** 2 / 2) * dt +\n",
    "                                         sigma * sqrt(dt) * rn[t, i])\n",
    "    return np.array(S) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 252 ms, sys: 34.7 ms, total: 287 ms\n",
      "Wall time: 243 ms\n"
     ]
    }
   ],
   "source": [
    "%time S = mcs_simulation_cy((M, I))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38.20316403735488"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S[-1].mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "235 ms ± 13.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit S = mcs_simulation_cy((M, I))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multiprocessing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "metadata": {},
   "outputs": [],
   "source": [
    "import multiprocessing as mp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {},
   "outputs": [],
   "source": [
    "pool = mp.Pool(processes=4)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {},
   "outputs": [],
   "source": [
    "p = 20  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "133 ms ± 5.93 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit S = np.hstack(pool.map(mcs_simulation_np, p * [(M, int(I / p))]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "122 ms ± 2.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit S = np.hstack(pool.map(mcs_simulation_nb, p * [(M, int(I / p))]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "122 ms ± 1.62 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit S = np.hstack(pool.map(mcs_simulation_cy, p * [(M, int(I / p))]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Recursive pandas Algorithm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data and Formula"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {},
   "outputs": [],
   "source": [
    "sym = 'SPY'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = pd.DataFrame(pd.read_csv('../../source/tr_eikon_eod_data.csv',\n",
    "                               index_col=0, parse_dates=True)[sym]).dropna()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "metadata": {},
   "outputs": [],
   "source": [
    "alpha = 0.25"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 152,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['EWMA'] = data[sym]  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 563 ms, sys: 16.7 ms, total: 580 ms\n",
      "Wall time: 565 ms\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "for t in zip(data.index, data.index[1:]):\n",
    "    data.loc[t[1], 'EWMA'] = (alpha * data.loc[t[1], sym] +\n",
    "                              (1 - alpha) * data.loc[t[0], 'EWMA'])  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 154,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SPY</th>\n",
       "      <th>EWMA</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2010-01-04</th>\n",
       "      <td>113.33</td>\n",
       "      <td>113.330000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-05</th>\n",
       "      <td>113.63</td>\n",
       "      <td>113.405000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-06</th>\n",
       "      <td>113.71</td>\n",
       "      <td>113.481250</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-07</th>\n",
       "      <td>114.19</td>\n",
       "      <td>113.658438</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-08</th>\n",
       "      <td>114.57</td>\n",
       "      <td>113.886328</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               SPY        EWMA\n",
       "Date                          \n",
       "2010-01-04  113.33  113.330000\n",
       "2010-01-05  113.63  113.405000\n",
       "2010-01-06  113.71  113.481250\n",
       "2010-01-07  114.19  113.658438\n",
       "2010-01-08  114.57  113.886328"
      ]
     },
     "execution_count": 154,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "data[data.index > '2017-1-1'].plot(figsize=(10, 6));\n",
    "# plt.savefig('../../images/ch10/perf_03.png');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pure Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ewma_py(x, alpha):\n",
    "    y = np.zeros_like(x)\n",
    "    y[0] = x[0]\n",
    "    for i in range(1, len(x)):\n",
    "        y[i] = alpha * x[i] + (1-alpha) * y[i-1]\n",
    "    return y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 30.8 ms, sys: 1.62 ms, total: 32.4 ms\n",
      "Wall time: 31.4 ms\n"
     ]
    }
   ],
   "source": [
    "%time data['EWMA_PY'] = ewma_py(data[sym], alpha)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2.08 ms, sys: 97 µs, total: 2.17 ms\n",
      "Wall time: 2.16 ms\n"
     ]
    }
   ],
   "source": [
    "%time data['EWMA_PY'] = ewma_py(data[sym].values, alpha)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numba"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "metadata": {},
   "outputs": [],
   "source": [
    "ewma_nb = numba.jit(ewma_py)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 160,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 205 ms, sys: 8.81 ms, total: 214 ms\n",
      "Wall time: 218 ms\n"
     ]
    }
   ],
   "source": [
    "%time data['EWMA_NB'] = ewma_nb(data[sym], alpha)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "30.4 ms ± 2.34 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit data['EWMA_NB'] = ewma_nb(data[sym], alpha)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 78.8 ms, sys: 2.3 ms, total: 81.1 ms\n",
      "Wall time: 80.1 ms\n"
     ]
    }
   ],
   "source": [
    "%time data['EWMA_NB'] = ewma_nb(data[sym].values, alpha)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "118 µs ± 4.76 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit data['EWMA_NB'] = ewma_nb(data[sym].values, alpha)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cython"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%cython\n",
    "import numpy as np\n",
    "cimport cython\n",
    "@cython.boundscheck(False)\n",
    "@cython.wraparound(False)\n",
    "def ewma_cy(double[:] x, float alpha):\n",
    "    cdef int i\n",
    "    cdef double[:] y = np.empty_like(x)\n",
    "    y[0] = x[0]\n",
    "    for i in range(1, len(x)):\n",
    "        y[i] = alpha * x[i] + (1 - alpha) * y[i - 1]\n",
    "    return y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 165,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2.46 ms, sys: 973 µs, total: 3.44 ms\n",
      "Wall time: 3.26 ms\n"
     ]
    }
   ],
   "source": [
    "%time data['EWMA_CY'] = ewma_cy(data[sym].values, alpha)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "577 µs ± 16.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit data['EWMA_CY'] = ewma_cy(data[sym].values, alpha)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SPY</th>\n",
       "      <th>EWMA</th>\n",
       "      <th>EWMA_PY</th>\n",
       "      <th>EWMA_NB</th>\n",
       "      <th>EWMA_CY</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2010-01-04</th>\n",
       "      <td>113.33</td>\n",
       "      <td>113.330000</td>\n",
       "      <td>113.330000</td>\n",
       "      <td>113.330000</td>\n",
       "      <td>113.330000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-05</th>\n",
       "      <td>113.63</td>\n",
       "      <td>113.405000</td>\n",
       "      <td>113.405000</td>\n",
       "      <td>113.405000</td>\n",
       "      <td>113.405000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-06</th>\n",
       "      <td>113.71</td>\n",
       "      <td>113.481250</td>\n",
       "      <td>113.481250</td>\n",
       "      <td>113.481250</td>\n",
       "      <td>113.481250</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-07</th>\n",
       "      <td>114.19</td>\n",
       "      <td>113.658438</td>\n",
       "      <td>113.658438</td>\n",
       "      <td>113.658438</td>\n",
       "      <td>113.658438</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-08</th>\n",
       "      <td>114.57</td>\n",
       "      <td>113.886328</td>\n",
       "      <td>113.886328</td>\n",
       "      <td>113.886328</td>\n",
       "      <td>113.886328</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               SPY        EWMA     EWMA_PY     EWMA_NB     EWMA_CY\n",
       "Date                                                              \n",
       "2010-01-04  113.33  113.330000  113.330000  113.330000  113.330000\n",
       "2010-01-05  113.63  113.405000  113.405000  113.405000  113.405000\n",
       "2010-01-06  113.71  113.481250  113.481250  113.481250  113.481250\n",
       "2010-01-07  114.19  113.658438  113.658438  113.658438  113.658438\n",
       "2010-01-08  114.57  113.886328  113.886328  113.886328  113.886328"
      ]
     },
     "execution_count": 167,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SPY</th>\n",
       "      <th>EWMA</th>\n",
       "      <th>EWMA_PY</th>\n",
       "      <th>EWMA_NB</th>\n",
       "      <th>EWMA_CY</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2018-06-25</th>\n",
       "      <td>271.00</td>\n",
       "      <td>274.535176</td>\n",
       "      <td>274.535176</td>\n",
       "      <td>274.535176</td>\n",
       "      <td>274.535176</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2018-06-26</th>\n",
       "      <td>271.60</td>\n",
       "      <td>273.801382</td>\n",
       "      <td>273.801382</td>\n",
       "      <td>273.801382</td>\n",
       "      <td>273.801382</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2018-06-27</th>\n",
       "      <td>269.35</td>\n",
       "      <td>272.688537</td>\n",
       "      <td>272.688537</td>\n",
       "      <td>272.688537</td>\n",
       "      <td>272.688537</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2018-06-28</th>\n",
       "      <td>270.89</td>\n",
       "      <td>272.238903</td>\n",
       "      <td>272.238903</td>\n",
       "      <td>272.238903</td>\n",
       "      <td>272.238903</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2018-06-29</th>\n",
       "      <td>271.28</td>\n",
       "      <td>271.999177</td>\n",
       "      <td>271.999177</td>\n",
       "      <td>271.999177</td>\n",
       "      <td>271.999177</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               SPY        EWMA     EWMA_PY     EWMA_NB     EWMA_CY\n",
       "Date                                                              \n",
       "2018-06-25  271.00  274.535176  274.535176  274.535176  274.535176\n",
       "2018-06-26  271.60  273.801382  273.801382  273.801382  273.801382\n",
       "2018-06-27  269.35  272.688537  272.688537  272.688537  272.688537\n",
       "2018-06-28  270.89  272.238903  272.238903  272.238903  272.238903\n",
       "2018-06-29  271.28  271.999177  271.999177  271.999177  271.999177"
      ]
     },
     "execution_count": 168,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"http://hilpisch.com/tpq_logo.png\" alt=\"The Python Quants\" width=\"35%\" align=\"right\" border=\"0\"><br>\n",
    "\n",
    "<a href=\"http://tpq.io\" target=\"_blank\">http://tpq.io</a> | <a href=\"http://twitter.com/dyjh\" target=\"_blank\">@dyjh</a> | <a href=\"mailto:training@tpq.io\">training@tpq.io</a>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
